package com.tedu.element.player;

import java.awt.*;
import java.util.List;
import java.util.Set;

import javax.swing.ImageIcon;

import com.tedu.controller.GameListener;
import com.tedu.element.bubble.Bubble;
import com.tedu.element.Direction;
import com.tedu.element.ElementObj;
import com.tedu.element.bubble.BubbleExplosionListener;
import com.tedu.element.map.GameMap;
import com.tedu.element.map.MapAware;
import com.tedu.element.map.MapObj;
import com.tedu.manager.ElementManager;
import com.tedu.manager.GameElement;
import com.tedu.manager.GameLoad;
import com.tedu.show.GameConstants;

/**
 * 游戏玩家类
 */
public class Player extends ElementObj implements MapAware, BubbleExplosionListener {
    private int playerID;   // 玩家ID
    private PlayerInputStrategy inputStrategy;  // 输入策略

    private boolean moveUp = false;
    private boolean moveDown = false;
    private boolean moveLeft = false;
    private boolean moveRight = false;

    // 泡泡类新增属性
    private int bombCount = GameConstants.PLAYER_BUBBLE_COUNT; // 可放置泡泡数量
    private int activeBombCount = 0; // 当前活跃泡泡数量
    private int bombPower = GameConstants.PLAYER_BOMB_POWER; // 泡泡爆炸威力
    private boolean placeBubble = false; // 是否放置泡泡
    private boolean placeBubbleKey = false;

    private int frameX = 0; // 当前帧在精灵图中的X坐标
    private int frameY = 0; // 当前帧在精灵图中的Y坐标

    private final int playerSize = GameConstants.PLAYER_SIZE;

    // 记录角色方向，默认为 down
    private Direction direction = Direction.down;
    // 移动速度
    private int speed = 1;
    // 用于控制图片变化速度
    private long imgtime = 0;
    // 地图引用
    private GameMap gameMap;
    // 速度药水计时器
    private int speedItemCount = 0;

    // str = "x,y,imgName"
    @Override
    public ElementObj createElement(String str) {
        String[] split = str.split(",");
        this.setGridX(Integer.parseInt(split[0]));
        this.setGridY(Integer.parseInt(split[1]));
        ImageIcon icon = GameLoad.imgMap.get(split[2]);
        this.setIcon(icon);
        this.setW(icon.getIconWidth());
        this.setH(icon.getIconHeight());
        return this;
    }

    @Override
    public void showElement(Graphics g) {
        // 做图片的分割
        g.drawImage(this.getIcon().getImage(),
                this.getX(), this.getY(),
                this.getX() + playerSize,
                this.getY() + playerSize,
                26 + (frameX * 100), 42 + (frameY * 100),
                72 + (frameX * 100), 99 + (frameY * 100),
                null);

        // 调试模式显示碰撞框
        if (GameConstants.DEBUG_MODE) {
            g.setColor(new Color(255, 0, 0, 100));
            Rectangle rect = getRectangle();
            g.fillRect(rect.x, rect.y, rect.width, rect.height);
        }
    }

    @Override
    public void model(long gameTime) {
        // 处理输入
        if (inputStrategy != null) {
            Set<Integer> keys = GameListener.getPressedKeys();
            inputStrategy.handleInput(this, keys);
        }
        // 放置泡泡
        add(gameTime);
        // 移动
        move();
        // 更新图像
        updateImage(gameTime);
    }

    @Override
    protected void add(long gameTime) {
       boolean placeBubbleKeyNow = this.placeBubble;
       if (placeBubbleKeyNow && !this.placeBubbleKey) {
           placeBubble();
       }
       this.placeBubbleKey = placeBubbleKeyNow;
    }

    @Override
    protected void move() {
        // 根据方向标志计算新坐标
        int newX = getX();
        int newY = getY();

        if (this.moveUp) {
            newY -= speed;
        }
        if (this.moveDown) {
            newY += speed;
        }
        if (this.moveLeft) {
            newX -= speed;
        }
        if (this.moveRight) {
            newX += speed;
        }

        // 只有当坐标实际发生变化时才检查碰撞和移动
        if (newX != getX() || newY != getY()) {
            if (canMoveTo(newX, newY)) {
                this.setX(newX);
                this.setY(newY);
            }
        }
    }

    @Override
    protected void updateImage(long time) {
        frameY = direction.getSpriteRow();
        if (time - imgtime > GameConstants.PLAYER_ANIMATION_SPEED) {
            imgtime = time;
            frameX = (frameX + 1) % GameConstants.PLAYER_FRAME_COUNT;
        }
    }

    private boolean canMoveTo(int newX, int newY) {
        // 1. 边界检测: 检查角色是否会移出地图边界
        if (gameMap == null) {
            return true;
        }

        int tileSize = GameConstants.TILE_SIZE;
        int mapWidthPixels = gameMap.getGridWidth() * tileSize;
        int mapHeightPixels = gameMap.getGridHeight() * tileSize;
        if (newX < 0 || newX + playerSize > mapWidthPixels ||
                newY < 0 || newY + playerSize > mapHeightPixels) {
            return false; // 超出边界
        }

        // 2. 障碍物碰撞检测: 检查角色移动后的新位置是否会与障碍物碰撞
        // 定义内缩值，作为容错边距，防止角色被地图边角卡住
        int inset = playerSize / 16;

        // 计算内缩后碰撞盒的四个新顶点在地图网格上的坐标
        // 左上角
        int leftTopX = (newX + inset) / tileSize;
        int leftTopY = (newY + inset) / tileSize;
        // 右上角
        int rightTopX = (newX + playerSize - 1 - inset) / tileSize;
        int rightTopY = (newY + inset) / tileSize;
        // 左下角
        int leftBottomX = (newX + inset) / tileSize;
        int leftBottomY = (newY + playerSize - 1 - inset) / tileSize;
        // 右下角
        int rightBottomX = (newX + playerSize - 1 - inset) / tileSize;
        int rightBottomY = (newY + playerSize - 1 - inset) / tileSize;

        // 检查角点所在的格子是否为障碍物
        MapObj topLeft = gameMap.getTile(leftTopX, leftTopY);
        MapObj topRight = gameMap.getTile(rightTopX, rightTopY);
        MapObj bottomLeft = gameMap.getTile(leftBottomX, leftBottomY);
        MapObj bottomRight = gameMap.getTile(rightBottomX, rightBottomY);

        if ((topLeft != null && !topLeft.isWalkable()) ||
                (topRight != null && !topRight.isWalkable()) ||
                (bottomLeft != null && !bottomLeft.isWalkable()) ||
                (bottomRight != null && !bottomRight.isWalkable())) {
            return false; // 发生碰撞
        }

        // 3. 与泡泡的碰撞检测
        Rectangle playerRect = new Rectangle(newX, newY, playerSize, playerSize);
        List<ElementObj> bubbles = ElementManager.getManager().getElementsByKey(GameElement.BUBBLE);
        for (ElementObj obj : bubbles) {
            Bubble bubble = (Bubble) obj;
            Rectangle bubbleRect = bubble.getRectangle();
            // 玩家将要移动到的位置与泡泡重叠
            if (playerRect.intersects(bubbleRect)) {
                // 玩家当前位置没有与该泡泡重叠
                if (!this.getRectangle().intersects(bubbleRect)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 放置泡泡
     */
    private void placeBubble() {
        if (activeBombCount < bombCount) {
            // 获得泡泡实例
            ElementObj obj = GameLoad.getObj("bubble");
            if (obj != null) {
                Bubble bubble = (Bubble) obj.createElement(getGridX() + "," + getGridY() + "," + bombPower);
                // 将 Player 持有的地图引用注入到 Bubble 中
                bubble.setGameMap(gameMap);
                // 设置爆炸回调监听器为当前玩家实例
                bubble.setExplosionListener(this);
                ElementManager.getManager().addElement(bubble, GameElement.BUBBLE);
                activeBombCount++;
            }
        }
    }

    /**
     * 泡泡爆炸后回调
     */
    @Override
    public void onBubbleExploded(Bubble bubble) {
        if (activeBombCount > 0) {
            activeBombCount--;
        }
    }

    /**
     * 增加爆炸威力
     */
    public void increaseBombPower() {
        bombPower = Math.min(bombPower + 1, 5); // 最大5格
        System.out.printf("[Player%d] bombPower: %d\n", playerID, bombPower);
    }

    /**
     * 增加泡泡数量
     */
    public void increaseBombCount() {
        bombCount = Math.min(bombCount + 1, 5); // 最多5个
        System.out.printf("[Player%d] bombCount: %d\n", playerID, bombCount);
    }

    /**
     * 增加移动速度
     */
    public void increaseSpeed() {
        speedItemCount += 1;
        System.out.printf("[Player%d] 拾取速度药水\n", playerID);
        if (speed == 1) {
            if (speedItemCount == 2) {   // 1到 2 捡两次加速
                speed = Math.min(speed + 1, 3);
                speedItemCount = 0;
            }
        } else if (speed == 2) {
            if (speedItemCount == 3) {  // 2到 3 捡三次踩加速
                speed = 3;
                speedItemCount = 0;
            }
        } else {
            speedItemCount = 0;
        }
    }

    @Override
    public void setGameMap(GameMap gameMap) {
        this.gameMap = gameMap;
    }

    @Override
    public void setLive(boolean live) {
        super.setLive(live);
    }

    @Override
    public Rectangle getRectangle() {
        return new Rectangle(getX(), getY(), playerSize, playerSize);
    }

    @Override
    public int pixelToGrid(int pixel, int tileSize) {
        return (pixel + playerSize / 2) / tileSize;
    }

    public int getPlayerID() {
        return playerID;
    }

    public void setPlayerID(int playerID) {
        this.playerID = playerID;
    }

    public PlayerInputStrategy getInputStrategy() {
        return inputStrategy;
    }

    public void setInputStrategy(PlayerInputStrategy inputStrategy) {
        this.inputStrategy = inputStrategy;
    }

    public boolean isMoveUp() {
        return moveUp;
    }

    public void setMoveUp(boolean moveUp) {
        this.moveUp = moveUp;
    }

    public boolean isMoveDown() {
        return moveDown;
    }

    public void setMoveDown(boolean moveDown) {
        this.moveDown = moveDown;
    }

    public boolean isMoveLeft() {
        return moveLeft;
    }

    public void setMoveLeft(boolean moveLeft) {
        this.moveLeft = moveLeft;
    }

    public boolean isMoveRight() {
        return moveRight;
    }

    public void setMoveRight(boolean moveRight) {
        this.moveRight = moveRight;
    }

    public boolean isPlaceBubble() {
        return placeBubble;
    }

    public void setPlaceBubble(boolean placeBubble) {
        this.placeBubble = placeBubble;
    }

    public Direction getDirection() {
        return direction;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }
}
